/*
*  Copyright (C) 1998-2019 by Northwoods Software Corporation. All Rights Reserved.
*/

import * as go from '../release/go';
import { DrawCommandHandler } from './DrawCommandHandler';
import { GuidedDraggingTool } from './GuidedDraggingTool';
import { ResizeMultipleTool } from './ResizeMultipleTool';
import { RotateMultipleTool } from './RotateMultipleTool';

let myDiagram: go.Diagram;

export function init() {

  // hides open HTML Element
  const openDoc = document.getElementById('openDocument');
  if (openDoc) openDoc.style.visibility = 'hidden';
  // hides remove HTML Element
  const removeDoc = document.getElementById('removeDocument');
  if (removeDoc) removeDoc.style.visibility = 'hidden';

  const $ = go.GraphObject.make;  // for more concise visual tree definitions

  myDiagram =
    $(go.Diagram, 'myDiagramDiv',
      {
        allowLink: false,  // no user-drawn links

        commandHandler: new DrawCommandHandler(),  // defined in DrawCommandHandler.js
        // default to having arrow keys move selected nodes
        'commandHandler.arrowKeyBehavior': 'move',
        // allow Ctrl-G to call groupSelection()
        'commandHandler.archetypeGroupData': { text: 'Group', isGroup: true },

        rotatingTool: new RotateMultipleTool(),  // defined in RotateMultipleTool.js

        resizingTool: new ResizeMultipleTool(),  // defined in ResizeMultipleTool.js

        draggingTool: new GuidedDraggingTool(),  // defined in GuidedDraggingTool.js
        'draggingTool.horizontalGuidelineColor': 'blue',
        'draggingTool.verticalGuidelineColor': 'blue',
        'draggingTool.centerGuidelineColor': 'green',
        'draggingTool.guidelineWidth': 1,

        // notice whenever the selection may have changed
        'ChangedSelection': enableAll,  // defined below, to enable/disable commands

        // notice when the Paste command may need to be reenabled
        'ClipboardChanged': enableAll,

        // notice when an object has been dropped from the palette
        'ExternalObjectsDropped': function (e: go.DiagramEvent) {
          const elt = document.getElementById('myDiagramDiv');
          if (elt) elt.focus();  // assume keyboard focus should be on myDiagram
          (myDiagram.toolManager.draggingTool as GuidedDraggingTool).clearGuidelines();  // remove any guidelines
        }

      });


  // sets the qualities of the tooltip
  const tooltiptemplate =
    $<go.Adornment>('ToolTip',
      $(go.TextBlock,
        { margin: 3, editable: true },
        // converts data about the part into a string
        new go.Binding('text', '', function (data) {
          if (data.item !== undefined) return data.item;
          return '(unnamed item)';
        }))
    );

  // Define the generic furniture and structure Nodes.
  // The Shape gets it Geometry from a geometry path string in the bound data.
  myDiagram.nodeTemplate =
    $(go.Node, 'Spot',
      {
        locationObjectName: 'SHAPE',
        locationSpot: go.Spot.Center,
        toolTip: tooltiptemplate,
        selectionAdorned: false  // use a Binding on the Shape.stroke to show selection
      },
      // remember the location of this Node
      new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
      // move a selected part into the Foreground layer, so it isn't obscured by any non-selected parts
      new go.Binding('layerName', 'isSelected', function (s) { return s ? 'Foreground' : ''; }).ofObject(),
      // can be resided according to the user's desires
      { resizable: true, resizeObjectName: 'SHAPE' },
      { rotatable: true, rotateObjectName: 'SHAPE' },
      $(go.Shape,
        {
          name: 'SHAPE',
          // the following are default values;
          // actual values may come from the node data object via data-binding
          geometryString: 'F1 M0 0 L20 0 20 20 0 20 z',
          fill: 'rgb(130, 130, 256)'
        },
        // this determines the actual shape of the Shape
        new go.Binding('geometryString', 'geo'),
        // allows the color to be determined by the node data
        new go.Binding('fill', 'color'),
        // selection causes the stroke to be blue instead of black
        new go.Binding('stroke', 'isSelected', function (s) { return s ? 'dodgerblue' : 'black'; }).ofObject(),
        // remember the size of this node
        new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify),
        // can set the angle of this Node
        new go.Binding('angle', 'angle').makeTwoWay()
      )
    );

  myDiagram.nodeTemplate.contextMenu =
    $<go.Adornment>('ContextMenu',
      $('ContextMenuButton',
        $(go.TextBlock, 'Rename', { margin: 3 }),
        { click: function (e: go.InputEvent, obj: go.GraphObject) { rename(obj); } }),
      $('ContextMenuButton',
        $(go.TextBlock, 'Cut', { margin: 3 }),
        { click: function (e: go.InputEvent, obj: go.GraphObject) { myDiagram.commandHandler.cutSelection(); } }),
      $('ContextMenuButton',
        $(go.TextBlock, 'Copy', { margin: 3 }),
        { click: function (e: go.InputEvent, obj: go.GraphObject) { myDiagram.commandHandler.copySelection(); } }),
      $('ContextMenuButton',
        $(go.TextBlock, 'Rotate +45', { margin: 3 }),
        { click: function (e: go.InputEvent, obj: go.GraphObject) { (myDiagram.commandHandler as DrawCommandHandler).rotate(45); } }),
      $('ContextMenuButton',
        $(go.TextBlock, 'Rotate -45', { margin: 3 }),
        { click: function (e: go.InputEvent, obj: go.GraphObject) { (myDiagram.commandHandler as DrawCommandHandler).rotate(-45); } }),
      $('ContextMenuButton',
        $(go.TextBlock, 'Rotate +90', { margin: 3 }),
        { click: function (e: go.InputEvent, obj: go.GraphObject) { (myDiagram.commandHandler as DrawCommandHandler).rotate(90); } }),
      $('ContextMenuButton',
        $(go.TextBlock, 'Rotate -90', { margin: 3 }),
        { click: function (e: go.InputEvent, obj: go.GraphObject) { (myDiagram.commandHandler as DrawCommandHandler).rotate(-90); } }),
      $('ContextMenuButton',
        $(go.TextBlock, 'Rotate 180', { margin: 3 }),
        { click: function (e: go.InputEvent, obj: go.GraphObject) { (myDiagram.commandHandler as DrawCommandHandler).rotate(180); } })
    );


  // group settings from basic.html to lock things together
  myDiagram.groupTemplate =
    $(go.Group, go.Panel.Auto,
      {
        ungroupable: true,  // enable Ctrl-Shift-G to ungroup a selected Group
        toolTip: tooltiptemplate
      },
      $(go.Shape, 'Rectangle',  // the Group is not seen but can be selected due to the transparent fill
        { fill: 'transparent', stroke: 'lightgray', strokeWidth: 1 }),
      $(go.Placeholder)
    );

  // make grouped Parts unselectable
  myDiagram.addDiagramListener('SelectionGrouped', (e: go.DiagramEvent) => {
    // e.subject should be the new Group
    e.subject.memberParts.each((part: go.Part) => { part.selectable = false; });
  });

  myDiagram.addDiagramListener('SelectionUngrouped', (e: go.DiagramEvent) => {
    // e.parameter should be collection of ungrouped former members
    e.parameter.each((part: go.Part) => {
      part.selectable = true;
      part.isSelected = true;
    });
  });

  myDiagram.addDiagramListener('SelectionCopied', (e: go.DiagramEvent) => {
    // selection collection will be modified during this loop,
    // so make a copy of it first
    const sel = myDiagram.selection.toArray();
    for (let i = 0; i < sel.length; i++) {
      const part = sel[i];
      // don't have any members of Groups be selected or selectable
      if (part instanceof go.Group) {
        const mems = new go.Set<go.Part>().addAll(part.memberParts);
        mems.each(function (member) {
          member.isSelected = false;
          member.selectable = false;
        });
      }
    }
  });

  // change the title to indicate that the diagram has been modified
  myDiagram.addDiagramListener('Modified', (e: go.DiagramEvent) => {
    const currentFile = document.getElementById('currentFile');
    if (currentFile === null) return;
    const text = currentFile.textContent || '';
    const idx = text.indexOf('*');
    if (myDiagram.isModified) {
      if (idx < 0) currentFile.textContent = text + '*';
    } else {
      if (idx >= 0) currentFile.textContent = text.substr(0, idx);
    }
  });


  // the Palette

  // brushes for furniture structures
  const wood = $(go.Brush, 'Linear', { 0: '#964514', 1: '#5E2605' });
  const wall = $(go.Brush, 'Linear', { 0: '#A8A8A8', 1: '#545454' });
  const blue = $(go.Brush, 'Linear', { 0: '#42C0FB', 1: '#009ACD' });
  const metal = $(go.Brush, 'Linear', { 0: '#A8A8A8', 1: '#474747' });
  const green = $(go.Brush, 'Linear', { 0: '#9CCB19', 1: '#698B22' });

  // default structures and furniture
  const myPalette =
    $(go.Palette, 'myPaletteDiv',
      {
        nodeTemplate: myDiagram.nodeTemplate,  // shared with the main Diagram
        'contextMenuTool.isEnabled': false,  // but disable context menus
        allowZoom: false,
        layout: $(go.GridLayout, { cellSize: new go.Size(1, 1), spacing: new go.Size(5, 5) }),
        // initialize the Palette with a few furniture and structure nodes
        model: $(go.GraphLinksModel,
          {
            nodeDataArray: [
              {
                key: 1,
                geo: 'F1 M0 0 L5,0 5,40 0,40 0,0z x M0,0 a40,40 0 0,0 -40,40 ',
                item: 'left door',
                color: wall
              },
              {
                key: 2,
                geo: 'F1 M0 0 L5,0 5,40 0,40 0,0z x M5,0 a40,40 0 0,1 40,40 ',
                item: 'right door',
                color: wall
              },
              {
                key: 3, angle: 90,
                geo: 'F1 M0,0 L0,100 12,100 12,0 0,0z',
                item: 'wall',
                color: wall
              },
              {
                key: 4, angle: 90,
                geo: 'F1 M0,0 L0,50 10,50 10,0 0,0 x M5,0 L5,50z',
                item: 'window',
                color: 'whitesmoke'
              },
              {
                key: 5,
                geo: 'F1 M0,0 L50,0 50,12 12,12 12,50 0,50 0,0 z',
                item: 'corner',
                color: wall
              },
              {
                key: 6,
                geo: 'F1 M0 0 L40 0 40 40 0 40 0 0 x M0 10 L40 10 x M 8 10 8 40 x M 32 10 32 40 z',
                item: 'arm chair',
                color: blue
              },
              {
                key: 7,
                geo: 'F1 M0 0 L80,0 80,40 0,40 0 0 x M0,10 L80,10 x M 7,10 7,40 x M 73,10 73,40 z',
                item: 'couch',
                color: blue
              },
              {
                key: 8,
                geo: 'F1 M0 0 L30 0 30 30 0 30 z',
                item: 'Side Table',
                color: wood
              },
              {
                key: 9,
                geo: 'F1 M0 0 L80,0 80,90 0,90 0,0 x M0,7 L80,7 x M 0,30 80,30 z',
                item: 'queen bed',
                color: green
              },
              {
                key: 10,
                geo: 'F1 M5 5 L30,5 35,30 0,30 5,5 x F M0 0 L 35,0 35,5 0,5 0,0 z',
                item: 'chair',
                color: wood
              },
              {
                key: 11,
                geo: 'F1 M0 0 L50,0 50,90 0,90 0,0 x M0,7 L50,7 x M 0,30 50,30 z',
                item: 'twin bed',
                color: green
              },
              {
                key: 12,
                geo: 'F1 M0 0 L0 60 80 60 80 0z',
                item: 'kitchen table',
                color: wood
              },
              {
                key: 13,
                geo: 'F1 M 0,0 a35,35 0 1,0 1,-1 z',
                item: 'round table',
                color: wood
              },
              {
                key: 14,
                geo: 'F1 M 0,0 L35,0 35,30 0,30 0,0 x M 5,5 L 30, 5 30,25 5,25 5,5 x M 17,2 L 17,10 19,10 19,2 17,2 z',
                item: 'kitchen sink',
                color: metal
              },
              {
                key: 15,
                geo: 'F1 M0,0 L55,0, 55,50, 0,50 0,0 x M 40,7 a 7,7 0 1 0 0.00001 0z x M 40,10 a 4,4 0 1 0 0.00001 0z x M 38,27 a 7,7 0 1 0 0.00001 0z x ' +
                     'M 38,30 a 4,4 0 1 0 0.00001 0z x M 16,27 a 7,7 0 1 0 0.00001 0z xM 16,30 a 4,4 0 1 0 0.00001 0z x M 14,7 a 7,7 0 1 0 0.00001 0z x ' +
                     'M 14,10 a 4,4 0 1 0 0.00001 0z',
                item: 'stove',
                color: metal
              },
              {
                key: 16,
                geo: 'F1 M0,0 L55,0, 55,50, 0,50 0,0 x F1 M0,51 L55,51 55,60 0,60 0,51 x F1 M5,60 L10,60 10,63 5,63z',
                item: 'refrigerator',
                color: metal
              },
              {
                key: 17,
                geo: 'F1 M0,0 100,0 100,40 0,40z',
                item: 'bookcase',
                color: wood
              },
              {
                key: 18,
                geo: 'F1 M0,0 70,0 70,50 0,50 0,0 x F1 M15,58 55,58 55,62 15,62 x F1 M17,58 16,50 54,50 53,58z',
                item: 'desk',
                color: wood
              }
            ]  // end nodeDataArray
          })  // end model
      });  // end Palette


  // the Overview

  const myOverview =
    $(go.Overview, 'myOverviewDiv',
      { observed: myDiagram, maxScale: 0.5 });

  // change color of viewport border in Overview
  (myOverview.box.elt(0) as go.Shape).stroke = 'dodgerblue';


  // start off with an empty document
  myDiagram.isModified = false;
  newDocument();

  if (!checkLocalStorage()) {
    const currentFile = document.getElementById('currentFile');
    if (currentFile) {
      currentFile.textContent = `Sorry! No web storage support. If you're using Internet Explorer / Microsoft Edge,
        you must load the page from a server for local storage to work.`;
    }
  }

  // Attach to the window for console manipulation
  (window as any).myDiagram = myDiagram;
} // end init


// enable or disable a particular button
export function enable(name: string, ok: boolean) {
  const button = document.getElementById(name) as any;
  if (button) button.disabled = !ok;
}

// enable or disable all context-sensitive command buttons
export function enableAll() {
  const cmdhnd = myDiagram.commandHandler as DrawCommandHandler;
  enable('Rename', myDiagram.selection.count > 0);
  enable('Undo', cmdhnd.canUndo());
  enable('Redo', cmdhnd.canRedo());
  enable('Cut', cmdhnd.canCutSelection());
  enable('Copy', cmdhnd.canCopySelection());
  enable('Paste', cmdhnd.canPasteSelection());
  enable('Delete', cmdhnd.canDeleteSelection());
  enable('SelectAll', cmdhnd.canSelectAll());
  enable('AlignLeft', cmdhnd.canAlignSelection());
  enable('AlignRight', cmdhnd.canAlignSelection());
  enable('AlignTop', cmdhnd.canAlignSelection());
  enable('AlignBottom', cmdhnd.canAlignSelection());
  enable('AlignCenterX', cmdhnd.canAlignSelection());
  enable('AlignCenterY', cmdhnd.canAlignSelection());
  enable('AlignRows', cmdhnd.canAlignSelection());
  enable('AlignColumns', cmdhnd.canAlignSelection());
  enable('AlignGrid', cmdhnd.canAlignSelection());
  enable('Rotate45', cmdhnd.canRotate());
  enable('Rotate_45', cmdhnd.canRotate());
  enable('Rotate90', cmdhnd.canRotate());
  enable('Rotate_90', cmdhnd.canRotate());
  enable('Rotate180', cmdhnd.canRotate());
}

// Commands for this application

// changes the item of the object
function rename(obj: go.GraphObject | null) {
  if (!obj) obj = myDiagram.selection.first();
  if (!obj) return;
  const part = obj.part;
  if (part === null) return;
  const data = part.data;
  if (data === null) return;
  myDiagram.startTransaction('rename');
  const newName = prompt('Rename ' + data.item + ' to:', data.item);
  myDiagram.model.setDataProperty(data, 'item', newName);
  myDiagram.commitTransaction('rename');
}

// shows/hides gridlines
// to be implemented onclick of a button
export function updateGridOption() {
  const grid = document.getElementById('grid') as any;
  if (!grid) return;
  myDiagram.startTransaction('grid');
  myDiagram.grid.visible = (grid.checked === true);
  myDiagram.commitTransaction('grid');
}

// enables/disables guidelines when dragging
export function updateGuidelinesOption() {
  // no transaction needed, because we are modifying a tool for future use
  const guide = document.getElementById('guidelines') as any;
  if (!guide) return;
  if (guide.checked === true) {
    (myDiagram.toolManager.draggingTool as GuidedDraggingTool).isGuidelineEnabled = true;
  } else {
    (myDiagram.toolManager.draggingTool as GuidedDraggingTool).isGuidelineEnabled = false;
  }
}

// enables/disables snapping tools, to be implemented by buttons
export function updateSnapOption() {
  // no transaction needed, because we are modifying tools for future use
  const snap = document.getElementById('snap') as any;
  if (!snap) return;
  if (snap.checked === true) {
    (myDiagram.toolManager.draggingTool as GuidedDraggingTool).isGridSnapEnabled = true;
    myDiagram.toolManager.resizingTool.isGridSnapEnabled = true;
  } else {
    myDiagram.toolManager.draggingTool.isGridSnapEnabled = false;
    myDiagram.toolManager.resizingTool.isGridSnapEnabled = false;
  }
}

// user specifies the amount of space between nodes when making rows and column
function askSpace(): number {
  const space = prompt('Desired space between nodes (in pixels):') || '0';
  return parseFloat(space);
}

// update arrowkey function
export function arrowMode() {
  // no transaction needed, because we are modifying the CommandHandler for future use
  const move = document.getElementById('move') as any;
  const select = document.getElementById('select') as any;
  const scroll = document.getElementById('scroll') as any;
  if (!move || !select || !scroll) return;
  if (move.checked === true) {
    (myDiagram.commandHandler as DrawCommandHandler).arrowKeyBehavior = 'move';
  } else if (select.checked === true) {
    (myDiagram.commandHandler as DrawCommandHandler).arrowKeyBehavior = 'select';
  } else if (scroll.checked === true) {
    (myDiagram.commandHandler as DrawCommandHandler).arrowKeyBehavior = 'scroll';
  }
}


const UnsavedFileName = '(Unsaved File)';

export function checkLocalStorage() {
  try {
    window.localStorage.setItem('item', 'item');
    window.localStorage.removeItem('item');
    return true;
  } catch (e) {
    return false;
  }
}

export function getCurrentFileName(): string {
  const currentFile = document.getElementById('currentFile');
  if (!currentFile) return '';
  const name = currentFile.textContent || '';
  if (name && name[name.length - 1] === '*') return name.substr(0, name.length - 1);
  return name;
}

export function setCurrentFileName(name: string): void {
  const currentFile = document.getElementById('currentFile');
  if (!currentFile) return;
  if (myDiagram.isModified) {
    name += '*';
  }
  currentFile.textContent = name;
}

export function newDocument() {
  // checks to see if all changes have been saved
  if (myDiagram.isModified) {
    const save = confirm('Would you like to save changes to ' + getCurrentFileName() + '?');
    if (save) {
      saveDocument();
    }
  }
  setCurrentFileName(UnsavedFileName);
  // loads an empty diagram
  myDiagram.model = new go.GraphLinksModel();
  myDiagram.undoManager.isEnabled = true;
  myDiagram.addModelChangedListener((e) => {
    if (e.isTransactionFinished) enableAll();
  });
  myDiagram.isModified = false;
}

// saves the current floor plan to local storage
export function saveDocument() {
  if (checkLocalStorage()) {
    const saveName = getCurrentFileName();
    if (saveName === UnsavedFileName) {
      saveDocumentAs();
    } else if (saveName) {
      saveDiagramProperties();
      window.localStorage.setItem(saveName, myDiagram.model.toJson());
      myDiagram.isModified = false;
    }
  }
}

// saves floor plan to local storage with a new name
export function saveDocumentAs() {
  if (checkLocalStorage()) {
    const saveName = prompt('Save file as...', getCurrentFileName());
    if (saveName && saveName !== UnsavedFileName) {
      setCurrentFileName(saveName);
      saveDiagramProperties();
      window.localStorage.setItem(saveName, myDiagram.model.toJson());
      myDiagram.isModified = false;
    }
  }
}

// checks to see if all changes have been saved -> shows the open HTML element
export function openDocument() {
  if (checkLocalStorage()) {
    if (myDiagram.isModified) {
      const save = confirm('Would you like to save changes to ' + getCurrentFileName() + '?');
      if (save) {
        saveDocument();
      }
    }
    openElement('openDocument', 'mySavedFiles');
  }
}

// shows the remove HTML element
export function removeDocument() {
  if (checkLocalStorage()) {
    openElement('removeDocument', 'mySavedFiles2');
  }
}

// these functions are called when panel buttons are clicked

export function loadFile() {
  const listbox = document.getElementById('mySavedFiles') as any;
  if (!listbox) return;
  // get selected filename
  let fileName;
  for (let i = 0; i < listbox.options.length; i++) {
    if (listbox.options[i].selected) fileName = listbox.options[i].text; // selected file
  }
  if (fileName !== undefined) {
    // changes the text of "currentFile" to be the same as the floor plan now loaded
    setCurrentFileName(fileName);
    // actually load the model from the JSON format string
    const savedFile = window.localStorage.getItem(fileName);
    if (!savedFile) return;

    myDiagram.model = go.Model.fromJson(savedFile);
    loadDiagramProperties();
    myDiagram.undoManager.isEnabled = true;
    myDiagram.addModelChangedListener(function (e) {
      if (e.isTransactionFinished) enableAll();
    });
    myDiagram.isModified = false;
    // eventually loadDiagramProperties will be called to finish
    // restoring shared saved model/diagram properties
  }
  closeElement('openDocument');
}

// Store shared model state in the Model.modelData property
// (will be loaded by loadDiagramProperties)
export function saveDiagramProperties() {
  (myDiagram.model.modelData as any).position = go.Point.stringify(myDiagram.position);
}

// Called by loadFile.
export function loadDiagramProperties(e?: go.ChangedEvent) {
  // set Diagram.initialPosition, not Diagram.position, to handle initialization side-effects
  const pos = (myDiagram.model.modelData as any).position;
  if (pos) myDiagram.initialPosition = go.Point.parse(pos);
}


// deletes the selected file from local storage
export function removeFile() {
  const listbox = document.getElementById('mySavedFiles2') as any;
  if (!listbox) return;
  // get selected filename
  let fileName;
  for (let i = 0; i < listbox.options.length; i++) {
    if (listbox.options[i].selected) fileName = listbox.options[i].text; // selected file
  }
  if (fileName !== undefined) {
    // removes file from local storage
    window.localStorage.removeItem(fileName);
    // the current document remains open, even if its storage was deleted
  }
  closeElement('removeDocument');
}

export function updateFileList(id: string) {
  // displays cached floor plan files in the listboxes
  const listbox = document.getElementById(id) as any;
  if (!listbox) return;
  // remove any old listing of files
  let last;
  while (last = listbox.lastChild) listbox.removeChild(last);
  // now add all saved files to the listbox
  for (const key in window.localStorage) {
    const storedFile = window.localStorage.getItem(key);
    if (!storedFile) continue;
    const option = document.createElement('option');
    option.value = key;
    option.text = key;
    listbox.add(option, null);
  }
}

export function openElement(id: string, listid: string) {
  const panel = document.getElementById(id);
  if (panel && panel.style.visibility === 'hidden') {
    updateFileList(listid);
    panel.style.visibility = 'visible';
  }
}

// hides the open/remove elements when the "cancel" button is pressed
export function closeElement(id: string) {
  const panel = document.getElementById(id);
  if (panel && panel.style.visibility === 'visible') {
    panel.style.visibility = 'hidden';
  }
}

export function undo() { myDiagram.commandHandler.undo(); }
export function redo() { myDiagram.commandHandler.redo(); }
export function cutSelection() { myDiagram.commandHandler.cutSelection(); }
export function copySelection() { myDiagram.commandHandler.copySelection(); }
export function pasteSelection() { myDiagram.commandHandler.pasteSelection(); }
export function deleteSelection() { myDiagram.commandHandler.deleteSelection(); }
export function selectAll() { myDiagram.commandHandler.selectAll(); }
export function alignLeft() { (myDiagram.commandHandler as DrawCommandHandler).alignLeft(); }
export function alignRight() { (myDiagram.commandHandler as DrawCommandHandler).alignRight(); }
export function alignTop() { (myDiagram.commandHandler as DrawCommandHandler).alignTop(); }
export function alignBottom() { (myDiagram.commandHandler as DrawCommandHandler).alignBottom(); }
export function alignCemterX() { (myDiagram.commandHandler as DrawCommandHandler).alignCenterX(); }
export function alignCenterY() { (myDiagram.commandHandler as DrawCommandHandler).alignCenterY(); }
export function rotate45() { (myDiagram.commandHandler as DrawCommandHandler).rotate(45); }
export function rotate_45() { (myDiagram.commandHandler as DrawCommandHandler).rotate(-45); }
export function rotate90() { (myDiagram.commandHandler as DrawCommandHandler).rotate(90); }
export function rotate_90() { (myDiagram.commandHandler as DrawCommandHandler).rotate(-90); }
export function rotate180() { (myDiagram.commandHandler as DrawCommandHandler).rotate(180); }
export function cancel1() { closeElement('openDocument'); }
export function cancel2() { closeElement('removeDocument'); }
export function alignRows() { (myDiagram.commandHandler as DrawCommandHandler).alignRow(askSpace()); }
export function alignColumns() { (myDiagram.commandHandler as DrawCommandHandler).alignColumn(askSpace()); }
